bitkeeper revision 1.384 (3f2811d05XH-ocmJE7ybblgMy3Q92A)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 30 Jul 2003 18:43:28 +0000 (18:43 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 30 Jul 2003 18:43:28 +0000 (18:43 +0000)
network.c, dev.c, perfc_defn.h:
  Networking fixes.

xen/include/xeno/perfc_defn.h
xen/net/dev.c
xenolinux-2.4.21-sparse/arch/xeno/drivers/network/network.c

index 7d2377c19fb8cecf24e626e6a1f58cdc769bdb1e..a4dfc6b8e13c1662498917b1eda3ac317c67a7df 100644 (file)
@@ -9,6 +9,7 @@ PERFCOUNTER_CPU( sched_run1,   "sched: calls to schedule" )
 PERFCOUNTER_CPU( sched_run2,   "sched: runs through scheduler" )
 PERFCOUNTER_CPU( sched_ctx,    "sched: context switches" )
 
+PERFCOUNTER( net_hypercalls, "network hypercalls" )
 PERFCOUNTER( net_rx_capacity_drop, "net rx capacity drop" )
 PERFCOUNTER( net_rx_delivered, "net rx delivered" )
 PERFCOUNTER( net_rx_tlbflush, "net rx tlb flushes" )
index f31219734f6863f78ae3296dd7c8001996f6d360..ec761a571067f59816fbd1a32ba81a0cfc3f0b71 100644 (file)
@@ -1811,6 +1811,8 @@ long do_net_update(void)
     u8 *g_data;
     unsigned short protocol;
 
+    perfc_incr(net_hypercalls);
+
     for ( idx = 0; idx < MAX_DOMAIN_VIFS; idx++ )
     {
         if ( (vif = current->net_vif_list[idx]) == NULL )
index d14f08a8f13cad53a46069452e482cd4bc7ecf84..06d06e96f3197d075b9241f1da5b4cc3a931f108 100644 (file)
@@ -64,6 +64,8 @@ struct net_private
     spinlock_t tx_lock;
     unsigned int idx; /* Domain-specific index of this VIF. */
 
+    unsigned int rx_bufs_to_notify;
+
     /*
      * {tx,rx}_skbs store outstanding skbuffs. The first entry in each
      * array is an index into a chain of free entries.
@@ -111,6 +113,7 @@ static int network_open(struct net_device *dev)
         return 0;
     }
 
+    np->rx_bufs_to_notify = 0;
     np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0;
     memset(&np->stats, 0, sizeof(np->stats));
     spin_lock_init(&np->tx_lock);
@@ -165,12 +168,9 @@ static void network_tx_buf_gc(struct net_device *dev)
     unsigned int i;
     struct net_private *np = dev->priv;
     struct sk_buff *skb;
-    unsigned long flags;
     unsigned int prod;
     tx_entry_t *tx_ring = np->net_ring->tx_ring;
 
-    spin_lock_irqsave(&np->tx_lock, flags);
-
     do {
         prod = np->net_idx->tx_resp_prod;
 
@@ -196,8 +196,6 @@ static void network_tx_buf_gc(struct net_device *dev)
         np->tx_full = 0;
         netif_wake_queue(dev);
     }
-
-    spin_unlock_irqrestore(&np->tx_lock, flags);
 }
 
 
@@ -230,19 +228,26 @@ static void network_alloc_rx_buffers(struct net_device *dev)
         np->net_ring->rx_ring[i].req.id   = (unsigned short)id;
         np->net_ring->rx_ring[i].req.addr = 
             virt_to_machine(get_ppte(skb->head));
-    }
 
-    /*
-     * We may have allocated buffers which have entries outstanding in
-     * the page update queue -- make sure we flush those first!
-     */
-    flush_page_update_queue();
+        np->rx_bufs_to_notify++;
+    }
 
-    np->net_idx->rx_req_prod = i;
+    if ( np->rx_bufs_to_notify > (RX_MAX_ENTRIES/4) )
+    {
+        /*
+         * We may have allocated buffers which have entries outstanding in the 
+         * page update queue -- make sure we flush those first!
+         */
+        flush_page_update_queue();
 
-    np->net_idx->rx_event = RX_RING_INC(np->rx_resp_cons);
+        np->net_idx->rx_req_prod = i;
+        
+        np->net_idx->rx_event = RX_RING_INC(np->rx_resp_cons);
+        
+        HYPERVISOR_net_update();
 
-    HYPERVISOR_net_update();
+        np->rx_bufs_to_notify = 0;
+    }
 }
 
 
@@ -272,7 +277,6 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
         netif_stop_queue(dev);
         return -ENOBUFS;
     }
-    i = np->net_idx->tx_req_prod;
 
     if ( (((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= PAGE_SIZE )
     {
@@ -284,6 +288,10 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
         skb = new_skb;
     }   
     
+    spin_lock_irq(&np->tx_lock);
+
+    i = np->net_idx->tx_req_prod;
+
     id = GET_ID_FROM_FREELIST(np->tx_skbs);
     np->tx_skbs[id] = skb;
 
@@ -294,18 +302,18 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
     np->net_idx->tx_req_prod = TX_RING_INC(i);
     atomic_inc(&np->tx_entries);
 
-    np->stats.tx_bytes += skb->len;
-    np->stats.tx_packets++;
+    network_tx_buf_gc(dev);
 
-    spin_lock_irq(&np->tx_lock);
     if ( atomic_read(&np->tx_entries) >= TX_MAX_ENTRIES )
     {
         np->tx_full = 1;
         netif_stop_queue(dev);
     }
+
     spin_unlock_irq(&np->tx_lock);
 
-    network_tx_buf_gc(dev);
+    np->stats.tx_bytes += skb->len;
+    np->stats.tx_packets++;
 
     HYPERVISOR_net_update();
 
@@ -316,12 +324,15 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
 static void network_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 {
     unsigned int i;
+    unsigned long flags;
     struct net_device *dev = (struct net_device *)dev_id;
     struct net_private *np = dev->priv;
     struct sk_buff *skb;
     rx_resp_entry_t *rx;
     
+    spin_lock_irqsave(&np->tx_lock, flags);
     network_tx_buf_gc(dev);
+    spin_unlock_irqrestore(&np->tx_lock, flags);
 
  again:
     for ( i  = np->rx_resp_cons;